using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;

namespace UWBGL_XNA_Lib10
{
    public class UWB_XNADrawHelper : UWB_DrawHelper
    {
		UWB_XNAD3DMatrixStack mMatrixStack;

        public UWB_XNADrawHelper()
        {
			mMatrixStack = new UWB_XNAD3DMatrixStack();
        }

        public override bool drawPoint(Vector3 position)
        {
			GraphicsDevice device = UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice();
			Debug.Assert(device != null, "device not valid on DrawHelper drawCircle call");

			DeviceVertexFormat[] v = new DeviceVertexFormat[1];
			v[0].Position = position;
			v[0].Color = mColor1;

			float pointSize = device.RenderState.PointSize;
			device.RenderState.PointSize = mPointSize;

			device.DrawUserPrimitives(PrimitiveType.PointList, v, 0, 1);

            return true;
        }

        public override bool drawLine(Vector3 start, Vector3 end)
        {
			GraphicsDevice device = UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice();
			Debug.Assert(device != null, "device not valid on DrawHelper drawCircle call");

			DeviceVertexFormat[] v = new DeviceVertexFormat[2];

			Color flatColor = mColor1;

			v[0].Position = start;
			v[0].Color = flatColor;
			v[1].Position = end;
			if (mShadeMode == eShadeMode.smFlat)
				v[1].Color = flatColor;
			else
				v[1].Color = mColor2;

			device.DrawUserPrimitives(PrimitiveType.LineList, v, 0, 1);

            return true;
        }

        public override bool drawCircle(Vector3 center, float radius)
        {
			GraphicsDevice device = UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice();
            Debug.Assert(device != null, "device not valid on DrawHelper drawCircle call");
			if (radius > 0)
			{
				int kNumPts = 40;
				if (mLod == eLevelofDetail.lodLow)
					kNumPts = 10;
				else if (mLod == eLevelofDetail.lodMed)
					kNumPts = 20;
				DeviceVertexFormat[] v = new DeviceVertexFormat[kNumPts];

				float delta = (float)(UWB_Math.UWB_ToRadians((float)360 / (float)(kNumPts-2)));

				Color flatColor = mColor1;

				v[0].Position = new Vector3(center.X, center.Y, 0f);
				v[0].Color = flatColor;

				for (int i = 0; i < (kNumPts - 2); i++)
				{
					float X = center.X + (radius * (float)Math.Cos(i * delta));
					float Y = center.Y + (radius * (float)Math.Sin(i * delta));
					v[i + 1].Position = new Vector3(X, Y, 0f);
					v[i + 1].Color = flatColor;
				}
				v[kNumPts - 1] = v[1];

				if(mShadeMode == eShadeMode.smGouraud)
					v[0].Color = mColor2;
				
				device.DrawUserPrimitives(PrimitiveType.TriangleFan, v, 0, (kNumPts-2));
			}
            return true;
        }

		public override bool drawRectangle(Vector3 min, Vector3 max)
		{
			GraphicsDevice device = UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice();
			Debug.Assert(device != null, "device not valid on DrawHelper drawRectangle call");

			DeviceVertexFormat[] v = new DeviceVertexFormat[6];
			Color flatColor = mColor1;

			v[0].Position = Vector3.Divide((min + max), 2);
			v[0].Color = flatColor;

			v[1].Position = new Vector3(min.X, max.Y, max.Z);
			v[1].Color = flatColor;
			v[2].Position = min;
			v[2].Color = flatColor;
			v[3].Position = new Vector3(max.X, min.Y, max.Z);
			v[3].Color = flatColor;
			v[4].Position = max;
			v[4].Color = flatColor;
			v[5] = v[1];

			if (mShadeMode == eShadeMode.smGouraud)
				v[0].Color = mColor2;

			device.DrawUserPrimitives(PrimitiveType.TriangleFan, v, 0, 4);
			return true;
		}

        public override void setFillMode(eFillMode fillMode)
        {
            GraphicsDevice graphicsDevice = UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice();

            if (graphicsDevice != null)
            {
                switch (fillMode)
                {
                case eFillMode.fmSolid:
                    graphicsDevice.RenderState.FillMode = FillMode.Solid;
                    break;
                case eFillMode.fmPoint:
                    graphicsDevice.RenderState.FillMode = FillMode.Point;
                    break;
				case eFillMode.fmWireframe:
                    graphicsDevice.RenderState.FillMode = FillMode.WireFrame;
                    break;
                }
            }
        }


        // sets W,V,Rotation matrices
		public override bool accumulateModelTransform(
			Vector3 translation,
			Vector3 scale,
			float rotationRadians,
			Vector3 pivot)
		{
			if (UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice() == null)
				return false;

			Vector3 z_axis = new Vector3(0, 0, 1);
			mMatrixStack.TranslateLocal(translation);
			mMatrixStack.TranslateLocal(pivot);
			mMatrixStack.RotateAxisLocal(z_axis, rotationRadians);
			mMatrixStack.ScaleLocal(scale);
			mMatrixStack.TranslateLocal(-pivot);

			UWB_XNAGraphicsSystem.m_TheAPI.setWorldMatrix(mMatrixStack.Top());
			return true;

		}

		public override bool pushModelTransform()
		{
			if (UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice() == null)
				return false;

			mMatrixStack.Push();
			UWB_XNAGraphicsSystem.m_TheAPI.setWorldMatrix(mMatrixStack.Top());
			return true;
		}

		public override bool popModelTransform()
		{
			if (UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice() == null)
				return false;

			mMatrixStack.Pop();
			UWB_XNAGraphicsSystem.m_TheAPI.setWorldMatrix(mMatrixStack.Top());
			return true;
		}

		public override bool initializeModelTransform()
		{
			if (UWB_XNAGraphicsSystem.m_TheAPI.GetActiveDevice() == null)
				return false;

			mMatrixStack.LoadIdentity();
			UWB_XNAGraphicsSystem.m_TheAPI.setWorldMatrix(mMatrixStack.Top());
			return true;
		}
    }
}
